//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Bot Framework: http://botframework.com
//
// Bot Framework Emulator Github:
// https://github.com/Microsoft/BotFramwork-Emulator
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

import * as React from 'react';
import { mount, ReactWrapper } from 'enzyme';

import { SubMenu, SubMenuProps, SubMenuState } from './subMenu';

describe('<SubMenu />', () => {
  let wrapper: ReactWrapper<SubMenuProps, SubMenuState, SubMenu>;
  let instance: SubMenu;
  const focusHandler = jest.fn();

  beforeEach(() => {
    wrapper = mount(<SubMenu label={'Submenu'} index={0} items={[]} focusHandler={focusHandler} />);
    instance = wrapper.instance();
  });

  it('should render without any errors', () => {
    expect(instance).toBeTruthy();
  });

  it('should render a disabled submenu', () => {
    wrapper.setProps({ disabled: true });
    const outerLiElement = wrapper.getDOMNode<HTMLLIElement>();

    expect(outerLiElement.getAttribute('aria-label')).toBe('Submenu unavailable');
  });

  it('should show the submenu on a right arrow key press', () => {
    wrapper.setProps({ disabled: false });
    const mockEvent = { key: 'arrowright', preventDefault: jest.fn(), stopPropagation: jest.fn() };
    (instance as any).onKeyDown(mockEvent);

    expect(mockEvent.preventDefault).toHaveBeenCalled();
    expect(mockEvent.stopPropagation).toHaveBeenCalled();
    expect(wrapper.state().menuShowing).toBe(true);
  });

  it('should show the submenu on an enter key press', () => {
    wrapper.setProps({ disabled: false });
    const mockEvent = { key: 'enter', preventDefault: jest.fn(), stopPropagation: jest.fn() };
    (instance as any).onKeyDown(mockEvent);

    expect(mockEvent.preventDefault).toHaveBeenCalled();
    expect(mockEvent.stopPropagation).toHaveBeenCalled();
    expect(wrapper.state().menuShowing).toBe(true);
  });

  it('should hide the submenu on a left arrow key press', () => {
    wrapper.setProps({ disabled: false });
    wrapper.setState({ menuShowing: true });
    const mockEvent = { key: 'arrowleft', preventDefault: jest.fn(), stopPropagation: jest.fn() };
    (instance as any).onKeyDown(mockEvent);

    expect(mockEvent.stopPropagation).toHaveBeenCalled();
    expect(wrapper.state().menuShowing).toBe(false);
  });

  it('should hide the submenu on an escape key press', () => {
    wrapper.setProps({ disabled: false });
    wrapper.setState({ menuShowing: true });
    const mockEvent = { key: 'escape', preventDefault: jest.fn(), stopPropagation: jest.fn() };
    (instance as any).onKeyDown(mockEvent);

    expect(mockEvent.stopPropagation).toHaveBeenCalled();
    expect(wrapper.state().menuShowing).toBe(false);
  });

  it('should handle some other key press', () => {
    (instance as any).onKeyDown({ key: 'f' });
  });

  it('should show the submenu on mouse enter', () => {
    wrapper.setProps({ disabled: false });
    (instance as any).onMouseEnter();

    expect(wrapper.state().menuShowing).toBe(true);
  });

  it('should hide the submenu on mouse leave', () => {
    wrapper.setProps({ disabled: false });
    wrapper.setState({ menuShowing: true });
    (instance as any).onMouseLeave();

    expect(wrapper.state().menuShowing).toBe(false);
  });
});
